/*
	pcgm.v
	Program counter generation module
	
	This project and file(s) are released under GNU GPL v3.
	Please find license file from root directory.
	Meng Sun (c) 2013 <leon.meng.sun@gmail.com>
*/

module pcgm (EXTADDR, GCLK, GnRESET, COMPLEN, STACKEN, STACKMODE, MUXEXTPCR, PCRKEEP, PCRMODE, MEMADDR);

input [7:0] EXTADDR;
input GCLK, GnRESET; /*Global clock and reset*/
input COMPLEN; /*Enabler for 8->20 combiner*/
input STACKEN; /*Enabler for instruction address stack*/
input STACKMODE; /*Mode selection for instruction address stack, push or pop*/
input [1:0] MUXEXTPCR; /*PCR input selector*/
input PCRKEEP, PCRMODE; /*PCR control signal*/

output [19:0] MEMADDR;

wire [7:0] EXTADDR;
wire GCLK, GnRESET;
wire COMPLEN;
wire STACKEN;
wire STACKMODE;
wire [19:0] COMBINEROUT;
wire [19:0] STACKOUT;
wire [1:0] MUXEXTPCR;
reg [19:0] PCRi;
wire PCRKEEP, PCRMODE;

wire [19:0] MEMADDR;

always @ (COMBINEROUT or STACKOUT or MUXEXTPCR)
begin
	case (MUXEXTPCR)
	2'b00: begin /*NMI*/
		PCRi = 20'h10;
	end
	2'b01: begin /*INT*/
		PCRi = 20'h20;
	end
	2'b10: begin /*COMP*/
		PCRi = COMBINEROUT;
	end
	2'b11: begin /*STACK*/
		PCRi = STACKOUT;
	end
	endcase
end

comp8to20 CALLJUMPGEN (.Di(EXTADDR), .CLK(GCLK), .nRESET(GnRESET), .LEN(COMPLEN), .Do(COMBINEROUT));
istack INSADDRSTACK(.Di(MEMADDR), .CLK(GCLK), .nRESET(GnRESET), .EN(STACKEN), .MODE(STACKMODE), .Do(STACKOUT));
pcr PCREG (.ADDRi(PCRi), .CLK(GCLK), .nRESET(GnRESET), .KEEP(PCRKEEP), .MODE(PCRMODE), .MEMADDR(MEMADDR));

endmodule